Week 14 : Interface and Application programming



Objectives for Week 14

  1. Write an application that interfaces a user with an input and/or output device that I made


Rain game simulation using pygame


I decided try something simple just to understand how an interface works. One of my batchmates suggested trying out a python





Pygame is a cross-platform set of Python modules which is used to create video games. It consists of computer graphics and sound libraries designed to be used with the Python programming language.



I wanted to use the SAMD11 board created in the electronic design week


1. Program the board in Arduino IDE

#include <Arduino.h>

const int potPin = 14;  // Potentiometer connected to Arduino analog pin A0

void setup() {
  Serial.begin(9600);
}

void loop() {
  int intensity = analogRead(potPin);
  // intensity = map(intensity,0,1023,0,20);
  Serial.println(intensity);
  delay(100);  // Adjust delay as needed
}


Setting up the Environment:


  1. Initializing Pygame:
    • Import the necessary libraries: pygame , serial , and random .
    • Initialize Pygame and set up the game window and screen dimensions.
  1. Defining Colors and Raindrop Class:
    • Define color constants for the raindrops and background.
    • Create a Raindrop class to represent individual raindrops on the screen. The class should have attributes like position, speed, and color, along with methods for falling and drawing.
  1. Serial Communication Setup:
    • Specify the serial port ( COM21 in your case) and baud rate for communication with the SAMD11 board.
    • Create a serial object ( ser ) using the Serial class from the serial module.
  1. Game Loop:
    • Set up the main game loop ( while running: ) to handle game events and update the game state.
    • Use a clock object ( clock ) to control the frame rate.
  1. Reading Potentiometer Values:
    • Read potentiometer values from the SAMD11 board via serial communication ( ser.readline().decode().strip() ).
    • Convert the received string to an integer ( pot_value ) and handle any potential value errors.
  1. Mapping Potentiometer Values to Intensity:
    • Define a function ( map_value ) to map the potentiometer values to the desired rain intensity range (0-20 in the example).
    • Use this function to map the potentiometer value to the rain_intensity variable.
  1. Updating Rain Intensity and Color:
    • Update the rain intensity ( rain_intensity ) and corresponding color based on the mapped potentiometer value.
    • Adjust the color gradient based on different intensity ranges (e.g., blue to green, green to yellow, yellow to red).
  1. Generating Raindrops:
    • Create raindrops based on the rain intensity and color. Each raindrop should have random positions, speeds, and fall behavior.
  1. Rendering and Displaying Raindrops:
    • Draw and update each raindrop in the raindrops list within the game loop.
    • Clear the screen with the background color ( WHITE ) before drawing raindrops.
    • Update the display using pygame.display.flip() to show the changes.
  1. Handling Game Events and Exit:
    • Handle game events (e.g., quitting the game window) within the main game loop using Pygame's event system.
    • Use a variable ( running ) to control the game loop and exit gracefully when needed.
  1. Cap Frame Rate:
    • Use clock.tick(30) to cap the frame rate at 30 frames per second, ensuring smooth gameplay.







Python side

import pygame
import serial
import random

pygame.init()

# Screen dimensions
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Rain Game")

# Colors
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)
RED = (255, 0, 0)

# Raindrop class
class Raindrop:
    def __init__(self, x, y, speed, color):
        self.x = x
        self.y = y
        self.speed = speed
        self.color = color

    def fall(self):
        self.y += self.speed
        if self.y > height:
            self.y = 0

    def draw(self, screen):
        pygame.draw.line(screen, self.color, (self.x, self.y), (self.x, self.y + 10), 2)

# Serial communication with SAMD11
arduino_port = 'COM21'  # Update with your SAMD11's port
arduino_baudrate = 9600
ser = serial.Serial(arduino_port, arduino_baudrate)

clock = pygame.time.Clock()
running = True
raindrops = []
rain_intensity = 0
prev_pot_value = -1  # Set an initial previous potentiometer value

# Function to map a value from one range to another
def map_value(value, from_low, from_high, to_low, to_high):
    return int(to_low + (value - from_low) * (to_high - to_low) / (from_high - from_low))

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # Read intensity data from SAMD11 (potentiometer value)
    intensity_str = ser.readline().decode().strip()
    try:
        pot_value = int(intensity_str)
    except ValueError:
        pot_value = 0

    # Map the potentiometer value to the desired intensity range
    rain_intensity = map_value(pot_value, 0, 1023, 0, 1000)  # Example mapping to a range of 0-20
    colour_value = map_value(pot_value, 0, 1023, 0, 255)  # Example mapping to a range of 0-255
    # Update rain intensity and color if potentiometer value changes
    if pot_value != prev_pot_value:
        if pot_value >= 0:
            if colour_value <= 255:
                color = (0, colour_value, 255 - colour_value)  # Blue to Green gradient
            elif colour_value <= 511:
                color = (colour_value - 256, 255, 0)  # Green to Yellow gradient
            else:
                color = (255, 255 - (colour_value - 512), 0)  # Yellow to Red gradient
        prev_pot_value = pot_value
        print(color)
    # Clear the screen
    screen.fill(WHITE)

    # Generate raindrops based on rain intensity and color
    raindrops = []  # Clear the raindrops list
    for _ in range(rain_intensity):
        x = random.randint(0, width)
        y = random.randint(0, height)
        speed = random.randint(5, 20)
        raindrops.append(Raindrop(x, y, speed, color))

    # Draw and update raindrops
    for drop in raindrops:
        drop.fall()
        drop.draw(screen)

    # Update display
    pygame.display.flip()

    # Cap frame rate
    clock.tick(30)

pygame.quit()

I got the code from chatgpt


So my intent was to increase and decrease the intensity of raindrops according to the increase and decrease in the value of potentiometer

Here is how it looks like






MIT App inventor


I also tried using MIT app inventor a bit, but didn’t really finish the process.